#include<stdio.h>
#include <sys/types.h>      
#include <sys/socket.h>
#include<string.h>
#include <unistd.h>  
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <stdlib.h>

#define PORT 55555
#define IP "192.168.42.128"

//存储用户信息的结构体
struct User{
    char name[50];      //用户名
    char account[20];   //账号
    char password[20];  //密码 
    int flag;           //用来服务器的功能判断  1、注册  2、登录  3、注销
};

//收发信息的结构体
struct Infor{
	char faname[50];    //发送方用户名
	char jiename[50];     //接收方用户名
	char buff[1024];    //发送的消息
    int flag;           //用于功能的选择    1、私聊  2、群聊
};

//用于判断登录信息
struct User_name{  
	char name[50];
	int flag;
};

char line[1024]={0};
char *Myname=NULL;      //定义全局变量指针指定自己的用户名
pthread_t pd1,pd2;		//创建线程读信息的id
int clifd;					//客户端套接字
//struct sockaddr_in cliaddr;
struct sockaddr_in seraddr;

//连接服务器
int connectserve();
//登录功能选择视图
void menu();
//注册
void regist();
//登录
void login();
//注销
void logout();
//功能选择
void function();
//私聊
void prichat();
//私聊收取信息
void *receive_chat1();
//私聊记录
void prirecord();
//群聊
void grochat();
//群聊收取信息
void *receive_chat2();
//群聊记录
void grouprecord();

void savechat(FILE *fp,struct Infor in);
void pri(FILE *fp);

/**************************************************************** */
int main(){	
	if(connectserve()==0){
		return -1;
	}
    char flag;
	while(1){
		menu();
        printf("\n请输入选项:");
		scanf("%c",&flag);
		getchar();
		switch(flag){
			case '1':
				regist();
				break;			
			case '2':
				login();
				break;
			case '3':
				logout();
				break;
			case '4':
				return 0;
			default:
				break;
		}	
	}
	return 0;
}
/***************************************************************** */

void savechat(FILE *fp,struct Infor in){
	char lin[1096]={0};
	memset(lin,0,sizeof(lin));
	sprintf(lin,"%s:%s\n",in.jiename,in.buff);
	fputs(lin,fp);
	fclose(fp);
}
 
void pri(FILE *fp){
	memset(line,0,sizeof(line));
	while(fgets(line,1024,fp)){
		printf("%s",line);
		memset(line,0,sizeof(line));
	}
	fclose(fp);
}


//群聊记录
void grouprecord(){
	FILE *fp=fopen("Group_Chat.txt","a+");
	pri(fp);
}


//群聊收取信息
void *receive_chat2(){
	int num;
	struct Infor in;
	while(1){
		memset(&in,0,sizeof(in));
		num=read(clifd,&in,sizeof(in));
		if(num==0){
			printf("\n服务器关闭\n");
			return NULL;
		}
		if(in.flag==2){
			FILE *fp=fopen("Group_Chat.txt","a+");
			savechat(fp,in);
			printf("%s:  %s\n",in.jiename,in.buff);
			continue;
		}else if(in.flag==1){
			FILE *fp=fopen("Pri_Chat.txt","a+");
			FILE *pfp=fopen("Pri_tem.txt","a+");
			savechat(pfp,in);
			savechat(fp,in);	
		}
	}
}

//群聊
void grochat(){
	FILE *gfp=fopen("Gro_tem.txt","r");
	if(gfp!=NULL){
		pri(gfp);
		remove("Gro_tem.txt");	
	}
	struct Infor out;
	pthread_create(&pd2,NULL,receive_chat2,NULL);
	printf("\n友情提示: 输入quit退出!\n\n\n");
	while(1){
		memset(&out,0,sizeof(out));
		sprintf(out.faname,"%s",Myname);
		scanf("%s",out.buff);
		getchar();
		out.flag=2;
		if(strcmp(out.buff,"quit")==0){
        	pthread_cancel(pd2);
			return;
		}
		FILE *fp=fopen("Group_Chat.txt","a+");
		savechat(fp,out);
		write(clifd,&out,sizeof(out));
	}
}

//私聊记录
void prirecord(){
	FILE *fp=fopen("Pri_Chat.txt","a+");
	pri(fp);
 
}

//私聊收取信息
void *receive_chat1(){
	int num;
	struct Infor in;
	while(1){
		memset(&in,0,sizeof(in));
		num=read(clifd,&in,sizeof(in));
		if(num==0){
			printf("\n服务器关闭\n");
			return NULL;
		}
		if(in.flag==1){
			FILE *fp=fopen("Pri_Chat.txt","a+");
			savechat(fp,in);
			printf("\n%s:  %s\n",in.jiename,in.buff);
			continue;
		}else if(in.flag==2){
			FILE *fp=fopen("Group_Chat.txt","a+");
			FILE *gfp=fopen("Gro_tem.txt","a+");
			savechat(gfp,in);
			savechat(fp,in);
		}
	}
}

//私聊
void prichat(){
	FILE *pfp=fopen("Pri_tem.txt","r");
	if(pfp!=NULL){
		pri(pfp);
		remove("Pri_tem.txt");
	}
	char na_me[50]={0};
	struct Infor out;
	pthread_create(&pd1,NULL,receive_chat1,NULL);
	printf("请输入私聊的用户名: ");
	scanf("%s",na_me);
	getchar();
	printf("\n友情提示: 输入quit退出!\n\n");
	while(1){
		memset(&out,0,sizeof(out));
		sprintf(out.jiename,"%s",na_me);
		scanf("%s",out.buff);
		getchar();
		sprintf(out.faname,"%s",Myname);
		out.flag=1;
		if(strcmp(out.buff,"quit")==0){
			pthread_cancel(pd1);
			return;
		}
		FILE *fp=fopen("Pri_Chat.txt","a+");
		savechat(fp,out);
		write(clifd,&out,sizeof(out));
	}
}

//功能选择
void function(){
	char flag;
	while(1){
		printf("\n**************************\n");
		printf("****    1、私聊       ****\n");
		printf("****    2、群聊       ****\n");
		printf("****    3、私聊记录   ****\n");
		printf("****    4、群聊记录   ****\n");
		printf("****    5、退出       ****\n");
		printf("**************************\n\n");
		printf("请选择功能: ");
		scanf("%c",&flag);
		getchar();
		switch(flag){
			case '1':
				prichat();
				pthread_join(pd1,NULL);
				break;
			case '2':
				grochat();
				pthread_join(pd2,NULL);
				break;
			case '3':
				prirecord();
				break;
			case '4':
				grouprecord();
				break;
			case '5':
				return;
		}	
	}
}

//注销
void logout(){
	char flag[2];
	struct User user;
	printf("请输入要注销的账号:");
	scanf("%s",user.account);
	getchar();	
	printf("请输入密码:");
	scanf("%s",user.password);
	getchar();
	user.flag=3;
	write(clifd,&user,sizeof(user));
	read(clifd,flag,2);
	if(strcmp("1",flag)==0)
	{
		printf("\n\t注销成功     \n\n\n");
	}else{
		printf("\n    账号不存在     \n\n\n");
	}
}

//登录
void login(){
	struct User_name u_name;
	struct User user;
	printf("请输入账号:");
	scanf("%s",user.account);
	getchar();
	printf("请输入密码:");
	scanf("%s",user.password);
	getchar();
	user.flag=2;
	write(clifd,&user,sizeof(struct User));
	read(clifd,&u_name,sizeof(u_name));
	if(u_name.flag==1){
		printf("\n\t登录成功     \n");
		printf("\n    欢迎 %s 登录!!!   \n\n\n",u_name.name);
		Myname=u_name.name;
		function();
	}else{
		printf("\n     登录失败     \n\n\n");
	}
}

//注册
void regist(){
	char flag[2];
	struct User user;
	printf("请输入用户名:");
	scanf("%s",user.name);
	getchar();
	printf("请输入账号:");
	scanf("%s",user.account);
	getchar();
	printf("请输入密码:");
	scanf("%s",user.password);
	getchar();
	user.flag=1;
	write(clifd,&user,sizeof(struct User));
	read(clifd,flag,2);
	//printf("\n\t\t\t********************\n");
	if(strcmp("1",flag)==0){
		printf("\n注册成功\n\n\n");
	}else{
		printf("用户已存在\n");
	}
	//printf("\t\t\t********************\n\n");
}

//登录功能选择视图
void menu(){
    //system("clear");
	printf("**************************\n");
	printf("****欢迎来到网络聊天室****\n");
	printf("**************************\n");
	printf("****    1、注册       ****\n");
	printf("****    2、登录       ****\n");
	printf("****    3、注销       ****\n");
	printf("****    4、退出       ****\n");
	printf("**************************\n");
    printf("**************************\n");
}

//连接服务器
int connectserve(){
	int flag;
	clifd=socket(AF_INET,SOCK_STREAM,0);
	seraddr.sin_family = AF_INET; 
	seraddr.sin_port = htons(PORT);
	seraddr.sin_addr.s_addr = inet_addr(IP);
	flag=connect(clifd, (struct sockaddr*)&seraddr, sizeof(seraddr));
	if(flag==0){
		return 1;
	}
	printf("连接服务器失败!\n");
	return 0;
}